if ( !window.controller ) throw new Error( '"controller" not initialized' );
if ( !window.controller.display){
	//controller.display = controller.createAbstractInstance( 'display' );
	//alert(print_r(controller.Display));
	controller.display =  (function(){
		var instance;
		var Display = function(context){
			instance = this;
			this.context = context;
		}
		
		var DisplayPrototype = Display.prototype;
		DisplayPrototype.tpl = function(name, data, options){
			if (typeof(data) 	== "undefined") data = null;
			if (typeof(options) == "undefined") options = {};
			options.context = instance.context;
			//console.log('Get template #template_' + print_r(data));
			
			return $('#template_' + name).tmpl(data, options);
		}
		return Display;
	})();
	
	//controller.require('controller.display.Character');
}
if(!controller.Game){	
	controller.require('controller.events.EventDispatcher');
	controller.require('controller.Dialog');	
	
	controller.Game = function(){
		var $ = controller;
		var display;
		var Game = function(){
			GameSuperPrototype.constructor.call( this );
			display = new $.display(this);
			CreatGame.call(this);
			this._canUpdate = 0;
			
			
			// События Персонажа			
			wj_user.addEventListener("PROPERTY_UPDATE", 	this, eventPropertyUpdate);			
			wj_user.addEventListener("UPDATE_CLANS_DATA", 	this, eventUpdateClansData);																		
			wj_user.addEventListener("AJAX_END_COMMAND", this, UpdateDisplay);
			//wj_user.addEventListener("infoMessage", this, infoMessageHandler);
			
			this.dialog = new $.Dialog(this.app.dialog);
			
			var game = this;
			jQuery(window).hashchange( function(){game.parseCommandLocation()});
		    
            // Сразу подгружаем контролер меню и активного меню
            controller.require('controller.display.Menu');
            displays["Menu"] = new controller.display["Menu"](this, wj_user);
            controller.require('controller.display.Hot');
            displays["Hot"] = new controller.display["Hot"](this, wj_user);
            
            // Парсим строку адреса
			this.parseCommandLocation();
		}
		$.extend( Game, $.events.EventDispatcher );
		
		var GamePrototype = Game.prototype,
			GameSuperPrototype = Game.superPrototype;
		var dispatchEvent= GameSuperPrototype.dispatchEvent;
		var EEvent = $.events.Event;
		
		GamePrototype.get_display = function(){
			return display;
		}		

		var eventPropertyUpdate = function(e){
			//console.log("Property Event game");
			prop = wj_user.getPropertys();
			switch(e.data.id){
				case(1):
				case(2):
				case(3):
					updateMainBar("hp", prop[1].getValue(), prop[2].getValue());
				break;
				// Локации
				case(4):
				case(5):
					updateMainBar("location", prop[4].getValue(), prop[5].getValue());
				break;
				// Энергия	
				case(47):
				case(48):
				case(49):
					updateMainBar("energy", prop[47].getValue(), prop[48].getValue());
				break;
				// Криминал
				case(21):
				case(22):
					updateMainBar("prison", 100-prop[21].getValue(), prop[22].getValue());
				break;
			}
		// Перенаправляем событие вверх
			dispatchEvent.call(this, e);
		}						

		var eventUpdateClansData = function(e){
			if(c_m == "Clan"){
				this._canUpdate++;
			}			
		}			
				
		/* Смена Дисплеев **/
		var lastLocation = document.location;
		GamePrototype.parseCommandLocation = function(){
			var hash = this.parseLocation();            
			if(hash.m){
				
			//Если есть m это означает смена модуля отображения экрана
				//console.log("Change display detected");
			// Новый дисплей можем сохронять в куку для подъема с последнего места
				this.ChangeDisplay(hash);
			}
			if(hash.c){
				// Если есть в строке c это означает что это команда на сервер к контроллеру
				//delete(hash.c);
				this.commandProvider(hash.c, hash);
				//console.log("Command from the server detected "+hash.c);
			}
		}
		var comandID;
		GamePrototype.getComandID = function(){
			comandID = Math.random();
			return comandID;
		}
	
		GamePrototype.commandProvider = function(c, data){
		// Все вызовы команд
			if(data.twa && comandID == data.twa){
				var req = {};
			//console.log("Command twa access: "+c +" twa: "+ data.twa);
			// Команды связанные с юзером
				switch(c)
				{				
					// Новая ячейка
					case("newField"):						
						req.c = "Index";
						req.m = c;
                        if (curMove)
                        {
                            req.id = curMoveID;
                            req.x = data.x;
                            req.y = data.y;
                            curMove = false;
                            curMoveID = 0;
                        }
                        else
                        {      
                            req.x = data.x;
                            req.y = data.y;                      
                            req.color = data.color;
                            req.type = data.type;    
                        }
						
						wj_provider.Ajax(req);
                        curGeted = false;
					break;		
					
					// Удалить ячейку
					case("deleteField"):						
						req.c = "Index";
						req.m = c;
						req.id = data.id;						
						wj_provider.Ajax(req);
                        this.app.app.find("div#field_"+data.id+" div.menu div.yes").remove();
					break;		
                    
                    
                     // Удалить ячейку подтверждение
                    /*case("deleteFieldQuest"):  
                        //this.app.app.find("div#field_"+data.id+" div.menu div.icon").hide();
                        //this.app.app.find("div#field_"+data.id+" div.menu div.mdelete").show();
                        //this.app.app.find("div#field_"+data.id+" div.menu").append(display.tpl("Field_Menu_Delete", data));
                    break;  
                    
                    // Удалить ячейку подтверждение - отмена
                    case("deleteFieldCancel"):  
                        //this.app.app.find("div#field_"+data.id+" div.menu div.icon").hide();
                        //this.app.app.find("div#field_"+data.id+" div.menu div.menu").show();
                        //this.app.app.find("div#field_"+data.id+" div.menu").append(display.tpl("Field_Menu", data));
                    break;  */                                        
                    
                    // Удалить ячейку подтверждение
                    case("deleteFieldQuest"):  
                        this.app.app.find("div#field_"+data.id+" div.menu div.icon").remove();
                        this.app.app.find("div#field_"+data.id+" div.menu").append(display.tpl("Field_Menu_Delete", data));
                    break;  
                    
                    // Удалить ячейку подтверждение - отмена
                    case("deleteFieldCancel"):  
                        this.app.app.find("div#field_"+data.id+" div.menu div.icon").remove();
                        this.app.app.find("div#field_"+data.id+" div.menu").append(display.tpl("Field_Menu", data));
                    break;  
                                       					
					// Выйти
					case("logout"):						
						req.c = "Index";
						req.m = c;						
						wj_provider.Ajax(req);						
					break;		
					
					// Войти
					case("login"):						
						req.c = "Index";
						req.m = c;
						req.login = this.app.app.find('div.panel input#login').val();
						req.password = this.app.app.find('div.panel input#password').val();
						wj_provider.Ajax(req);
					break;	
					
					// Зарегистрироватся
					case("reg"):						
						req.c = "Index";
						req.m = c;
						req.login = this.app.app.find('div.panel input#login').val();
						req.password = this.app.app.find('div.panel input#password').val();
						wj_provider.Ajax(req);
					break;		
                    
                    // Перейти в ячейку
                    case("goInField"):                                                
                        req.c = "Index";
                        req.m = c;
                        req.id = data.id;
                        wj_provider.Ajax(req);
                    break;
                    
                    // Перейти на уровень выше
                    case("backDir"):         
                        this.app.app.css("overflow", "hidden");
                        
                        // Если в контэнте то просто выходти из него
                        if (inContent && data.id != -1)               
                        {                            
                            inContent = false;
                            this.Exec({"m": "Location", "op": "Index"});
                            if (!parseInt(wj_user.get("dir")))
                            {
                                this.dialog.Add(null, "Вернулись в корневую директорию", 2);
                            }
                            else
                            {
                                var field = wj_user.getField(parseInt(wj_user.get("dir")));
                                if (field)
                                    this.dialog.Add(null, "Вернулись в "+field.name, 2);
                                else
                                    this.dialog.Add(null, "Вернулись назад", 2);
                            }
                        }
                        // Если в папке то идём на уровень выше если не указан явный id директории
                        else
                        {
                            req.c = "Index";
                            req.m = c;
                            if (data.id)
                            {                          	
                                req.id = data.id;
                            }
                            else
                            {              
                            	var fields = wj_user.getFields();              	
                            	if (fields != null)
                            	{
                            		var id = 0;
                            		for(fid in fields)
                            		{
										var field = fields[fid];
										if (field.id == wj_user.get("dir"))
										{
											id = field.parent_id;
											break;
										}
                            		}
                            		if (id != 0)
										req.id = id;
								}
                            }
                            wj_provider.Ajax(req);    
                        }                        
                    break;
                    
                    // Скрыть показать панель быстрого создания ячеек
                    case("fastPanel"): 
                        this.app.amenu.find("div.content").toggle();
                    break;
                    
                    // Переместить ячейку
                    case("moveField"): 
                        if (wj_user.get("folders")[data.id])
                        {
                            var field = wj_user.get("folders")[data.id];
                            moveField(field.color, field.type);
                            curMove = true;
                            curMoveID = field.id;
                        }                        
                    break;
                    
                    // Редактировать ячейку
                    case("editField"):                        
                        this.editField(data.id);
                    break;      
                    
                    // Закрыть панель (редактирования ячейки)
                    case("closePanel"):                        
                        jQuery("body div#[panel_id="+data.id+"]").remove();
                    break;      
                    
                    // Сохранить настройки ячейки
                    case("saveField"):     
                        req.c = "Index";
                        req.m = c;
                        req.id = data.id;
                        req.field = {};
                        req.field.name = jQuery("div[panel_id=edit_"+data.id+"] input#name").val();
                        req.field.descr = jQuery("div[panel_id=edit_"+data.id+"] input#descr").val();
                        req.field.type = jQuery("div[panel_id=edit_"+data.id+"] select#type").val();
                        req.field.color = jQuery("div[panel_id=edit_"+data.id+"] select#color").val();
                        wj_provider.Ajax(req);                   
                        jQuery("body div#[panel_id=edit_"+data.id+"]").remove();
                    break;      
                    
                    // Редактировать контент ячейки
                    case("editFieldContent"):                          
                        this.app.app.css("overflow-y", "scroll");
                        switch(data.type)
                        {                            
                            case("back"):
                                data.type = "";
                            break;
                            case("html"):
                                this.app.app.css("overflow-y", "hidden");
                            break;
                            case("save"):
                                if (curEditMode == "html")                                
                                {
                                    req.c = "Index";
                                    req.m = "saveField";
                                    req.id = curEditID;
                                    req.field = {};
                                    req.field.content = tinyMCE.activeEditor.getContent();
                                    wj_provider.Ajax(req);                                        
                                }
                            break;
                        }
                        curEditMode = data.type;
                        this.Exec({"m":"Location", "op":"OpenContent", "id": curEditID});
                    break;																
					
					//this.dialog.Add("Настройка прав для братухи "+member.uname, display.tpl("Clan_MemberAccess", data), 4);
			
				}
				comandID = null;
			}
		
		}			
        
        // Инициализация TinyMCE
        GamePrototype.initTiny = function()
        {
            tinyMCE.init({
                mode : "textareas",
                theme : "advanced",
                language:"ru",
                plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
                document_base_url : (document.domain == "www.wizardjiocb.ru") ? "www.wizardjiocb.ru" : "wj",

                // Theme options
                theme_advanced_buttons1 : "bold,italic,underline,strikethrough|search,replace,|,bullist,numlist,|blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,code,|,preview,|,forecolor,backcolor|,iespell,media,advhr|ltr,rtl|fullscreen",
                theme_advanced_buttons2 : "tablecontrols,|,hr,removeformat,visualaid|insertlayer,moveforward,movebackward,absolute,|spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak|insertfile,insertimage",
                theme_advanced_toolbar_location : "top",
                theme_advanced_toolbar_align : "left",
                theme_advanced_statusbar_location : "bottom",
                theme_advanced_resizing : true,
                forced_root_block : false,
                force_br_newlines : true,
                force_p_newlines : false,
                skin : "o2k7",
                skin_variant : "silver",
                extended_valid_elements : 'script[type|src],iframe[src|style|width|height|scrolling|marginwidth|marginheight|frameborder],object[width|height|classid|codebase|embed|param],param[name|value],embed[param|src|type|width|height|flashvars|wmode],div[*],p[*]',
                media_strict: false,
                relative_urls : false,
                convert_urls : false
            });
        }
        
        // Создаём окошко редактирования ячейки
        GamePrototype.editField = function(id)
        {
            var field = wj_user.getField(id);
            jQuery("body").append(display.tpl("Field_Edit", {"id": id, "field": field}));
            jQuery("body div#panel[panel_id=edit_"+id+"]").css({left: (gx-90)+"px", top: (gy-66)+"px"});
        }
		
		GamePrototype.parseLocation = function(){
            //console.log("Location: "+window.location.hash);
            if (incLogin == 0)
            {
                incLoginData = window.location.hash;
                console.log("load");
            }
			var hashParams = {};
		    var e,
		        a = /\+/g,  // Regex for replacing addition symbol with a space
		        r = /([^&;=]+)=?([^&;]*)/g,
		        d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
		        q = window.location.hash.substring(1);

		    while (e = r.exec(q))
		       hashParams[d(e[1])] = d(e[2]);
			   
			//console.log(hashParams);
		    return hashParams;
		} 
		
		
		
		// Меняем только отображение !	
		var eventUserProcess = function(ev){
			//console.log("eventUserProcess:"+ev.action+"/"+ev.data.id);
			switch(ev.action){
				case "PROPERTY":
					// Распространить событие по шаблонам если это необходимо
					var prop = wj_user.get("property");
					switch(parseInt(ev.data.id)){
						// HP	
						case(1):
						case(2):
						case(3):
							updateMainBar("hp", prop[1], prop[2]);
						break;
						// Локации
						case(4):
						case(5):
							updateMainBar("location", prop[4],prop[5]);
						break;
						// Энергия	
						case(47):
						case(48):
						case(49):
							updateMainBar("energy", prop[47],prop[48]);
						break;
						// Криминал
						case(21):
						case(22):
							updateMainBar("prison", prop[21],prop[22]);
						break;
					}
					jQuery("#console_prop[rel='"+ev.data.id+"']").html(ev.data.value);
				break;
				case "BALANCE":
					updateMainBalance(ev.data.id, ev.data.value);
				break;
				case "STAT":
				
				break;
				case "DATA":
					// EXP, Level, победы, поражения
					for(var i in ev.data){
						switch(i){
							case("exp"):
								//Math.floor((userData.exp - exptable.exp_min)/(exptable.exp_max + 1 - exptable.exp_min)*100)
								var exptable = controller.User.exptable[wj_user.get("data.level")]	
								if(exptable.max < ev.data.exp){
									exptable = controller.User.exptable[wj_user.get("data.level") + 1];
								}
								//console.log(exptable);
								
								updateMainBar("exp", (ev.data.exp - exptable.exp_min), (exptable.exp_max - exptable.exp_min + 1));
								
							break;
							case("level"):
								jQuery("div.top > div.name > div.level").html(ev.data.level);
							break;
						}
					}
				break;
				case "USER":
					// Имя, пол, аватарка
					
				break;
			}
		}
		
		// Контроллер и метод
		var c_m, c_op = "index",c_hash;
		
		// Инстансы дисплеев
		var displays = {};
		var hash = {};
		
		// Возможные места отображения и изменения
		var app = {};
		
		// Доступные модули
		var modules   = {	
				// Основной контнент
				"Location": {
					"app" : "app",
					onAccept : function(){},
                    onLoad: function()
                    {
                        this.Exec({"m":"Menu"});
                        this.Exec({"m":"Hot"});
                        if (curEditMode == "html")
                            this.initTiny();
                    },
				}, 
                
                // Верхнее меню
                "Menu": {
                    "app" : "menu"
                    //onLoad: function(){jQuery("#papper").show();jQuery("#papper_wall").show()},
                    //onChangeDisplay: function(){jQuery("#papper").hide();jQuery("#papper_wall").hide()}
                },
                
                // Нижнее меню
                "Hot": {
                    "app" : "amenu"
                    //onLoad: function(){jQuery("#papper").show();jQuery("#papper_wall").show()},
                    //onChangeDisplay: function(){jQuery("#papper").hide();jQuery("#papper_wall").hide()}
                }
								
		};
		GamePrototype.getCM = function()
		{
			return c_m;
		}
		
		GamePrototype.getDis = function()
		{
			return display;
		}
		
		GamePrototype.getOP = function()
		{
			return c_op;
		}
		
		GamePrototype.getDisplay = function(name)
		{
			if (displays[name])
			{
				return displays[name];
			}
			return false;
		}
		
		GamePrototype.ChangeDisplay = function(hash){
			//hash = this.parseLocation();
			hash.op = (hash.op) ? hash.op : "Index";  
			hash.m = (hash.m) ? hash.m : "Location";
			// Если текущий модуль != новомe или сменилась опция отображения
				//	if(hash.m != c_m || hash.op != c_op ){
				// Меняем отображаемый модуль
				if(modules[hash.m]){
	
					if(modules[hash.m] && modules[hash.m].onAccept){							
						modules[hash.m].onAccept();
					}	
					
					if((c_m != hash.m || c_op != hash.op) && modules[c_m] && modules[c_m].onChangeDisplay){	
						//if (modules[c_m].app != modules[hash.m].app)
						{			
							modules[c_m].onChangeDisplay.call(this);
						}
					}
					c_m = hash.m;
					c_op = hash.op;
					c_hash = hash;
					//	console.log("Change display from "+c_m+" option "+ c_op);
					if(!displays[c_m]){
						controller.require('controller.display.'+c_m);
						displays[c_m] = new controller.display[c_m](this, wj_user);
					}
					//console.log(display.tpl(c_m+"_"+c_op, displays[c_m].getDisplay(c_op, hash), tw_user).html());
					//console.log(displays[c_m].getDisplay(c_op, hash));
					var app_data = displays[c_m].getDisplay(c_op, hash);					
					
					var html = display.tpl(c_m+"_"+c_op, app_data , wj_user);
					if (html != null)
						this.app[modules[c_m]["app"]].html(html);
					//jQuery("body").append(display.tpl(c_m+"_"+c_op, displays[c_m].getDisplay(c_op, hash), tw_user));
					if( modules[c_m] && modules[c_m].onLoad){
						modules[c_m].onLoad.call(this);
					}
				}
                else
                {
                    console.log("No module "+hash.m+" in loaded modules");
                }
				
		//	}
		}
        
        // Выполнить метод контроллера
        GamePrototype.Exec = function(data)
        {
            if (!data)
            {
                console.log("Exec: no data");
            }
            else
                this.ChangeDisplay(data);
        }
        
        GamePrototype.ExecC = function (data)
        {
            if (!data.c)
            {
                console.log("ExecC: no command in data");
                return false;
            }
            else
            {
                this.commandProvider(data.c, data);
            }
        }
        
		var UpdateDisplay = function(){			
			try{
				if(this._canUpdate > 0){
					//console.log("Update display");
					this.app[modules[c_m]["app"]].html(display.tpl(c_m+"_"+c_op, displays[c_m].getDisplay(c_op, c_hash), tw_user));
					this._canUpdate = 0;
				}else{
					//console.log("Update display ignore "+this._canUpdate);
				}
			//	this.ChangeDisplay({m:c_m, op:c_op, update:"update"});
			}catch(e){
				//console.log(e.message);
			}
			//app[modules[c_m]["app"]].html(display.tpl(c_m+"_"+c_op, displays[c_m].getDisplay(c_op, hash), tw_user));
		}
		GamePrototype.app = {};
				
		var CreatGame = function(){
			jQuery( "#tmpl_main" ).template( "tmpl_main" );
			// Префиксы линков вверхней части
			this.app.main = jQuery("body");
			this.app.app = this.app.main.find("div#gl_content");
            this.app.menu = this.app.main.find("div#gl_menu");
            this.app.amenu = this.app.main.find("td#gl_amenu");
			this.app.dialog = this.app.main.find("#gl_dialog");
			this.creatChat(true);
		
		}
		
		GamePrototype.creatChat = function(){
			
			var port = 5190;
			var host = 'townwars.ru';
			if (parseInt(wj_user.get("id")) == 1)
			{
				host = '192.168.0.242';
			}
			//if (isAuth)
				//var list = wj_user.get("plex_id").split("_");
			
			/*global_chat = new avangard.chat.ChatController(
					window.display(),
					host,
					5190,
					//85123,
					parseInt(wj_user.get("id")),
					'd41d8cd98f00b204e9800998ecf8427e'
			);			*/
			//ddf149f774774956fa6a375f4507b8e8
			//73278a4a86960eeb576a8fd4c9ec6997
		}
		
		
		
		
	return Game;
	}();
}


